import { Request, Response } from 'express';
import * as fs from 'fs';
import { getTimestampString } from './utils';

type MenuDataType = {
  menuTree: MENU.MenuType[];
  beUsedCode: string[];
  beUsedId: string[];
};

export const getMuneData = () => {
  const menuDataStr = fs.readFileSync('./mock/database/menu.json', 'utf-8');
  const menuData: MenuDataType = menuDataStr
    ? JSON.parse(menuDataStr)
    : {
        menuTree: [],
        beUsedCode: [],
        beUsedId: [],
      };
  return menuData;
};

const findMenuById = (menuTree: MENU.MenuType[], id: string): MENU.MenuType | undefined => {
  let findMenu = undefined;
  for (const item of menuTree) {
    if (item.id === id) {
      findMenu = item;
      break;
    }
    if (item.children && item.children.length > 0) {
      findMenu = findMenuById(item.children, id);
      if (findMenu) break;
    }
  }
  return findMenu;
};

// 菜单报错信息映射对象
const menuErrMessageMap: Record<string, string> = {
  pid: '父级菜单id不能为空！',
  id: '菜单id不能为空！',
  menuName: '父级菜单id不能为空！',
  link: '菜单路径（链接）不能为空！',
  menuCode: '菜单编码不能为空！',
  order: '菜单顺序不能为空！',
};

export default {
  'GET /api/menuTree': async (req: Request, res: Response) => {
    const menuData = getMuneData();
    res.send({
      data: menuData.menuTree,
      success: true,
    });
  },
  'GET /api/menu': async (req: Request, res: Response) => {
    console.log(req.query);
    const { id } = req.query as unknown as MENU.QueryMenuParams;
    if (!id) {
      res.send({
        data: null,
        errorMessage: '菜单id不可为空！',
        success: false,
      });
      return;
    }
    const menuData = getMuneData();
    const currentMenu = findMenuById(menuData.menuTree, id);
    if (!currentMenu) {
      res.send({
        data: null,
        errorMessage: '未找到该菜单',
        success: false,
      });
      return;
    }

    res.send({
      data: currentMenu,
      success: true,
    });
  },
  'POST /api/menu': async (req: Request, res: Response) => {
    const menuParams = req.body as unknown as MENU.AddMenuParams;
    const validateFieldsArr = ['pid', 'menuName', 'link', 'menuCode', 'order'];
    for (const key of validateFieldsArr) {
      if (!menuParams[key] && menuErrMessageMap.hasOwnProperty(key)) {
        res.send({
          data: null,
          errorMessage: menuErrMessageMap[key],
          success: false,
        });
        return;
      }
    }
    const menuData = getMuneData();
    if (menuData.beUsedCode.includes(menuParams.menuCode)) {
      res.send({
        data: null,
        errorMessage: '该菜单编码已存在！',
        success: false,
      });
      return;
    }

    const id = getTimestampString();
    const addMenu = {
      ...menuParams,
      checked: false,
      id,
    };
    if (menuParams.pid === '0') {
      menuData.menuTree.push(addMenu);
      // 一级菜单，对新增菜单，已有菜单做排序
      menuData.menuTree.sort((pre, next) => pre.order - next.order);
    } else {
      // 非一级菜单，寻找添加菜单的上一级，对当前层级新增菜单，已有菜单做排序
      const currentMenu = findMenuById(menuData.menuTree, menuParams.pid);
      if (currentMenu) {
        currentMenu.children ||= [];
        currentMenu.children.push(addMenu);
        currentMenu.children.sort((pre, next) => pre.order - next.order);
      } else {
        res.send({
          data: null,
          errorMessage: '待添加菜单的父级菜单未找到！',
          success: false,
        });
        return;
      }
    }
    menuData.beUsedCode.push(menuParams.menuCode);
    menuData.beUsedId.push(id);
    fs.writeFileSync('./mock/database/menu.json', JSON.stringify(menuData));
    res.send({
      success: true,
      data: null,
    });
  },
  'PUT /api/menu': async (req: Request, res: Response) => {
    const menuParams = req.body as unknown as MENU.EditMenuParams;
    const validateFieldsArr = ['pid', 'id', 'menuName', 'link', 'menuCode', 'order'];
    for (const key of validateFieldsArr) {
      if (!menuParams[key] && menuErrMessageMap.hasOwnProperty(key)) {
        res.send({
          data: null,
          errorMessage: menuErrMessageMap[key],
          success: false,
        });
        return;
      }
    }
    const menuData = getMuneData();
    const editMenu = findMenuById(menuData.menuTree, menuParams.id);
    console.log(editMenu);
    if (!editMenu) {
      res.send({
        data: null,
        errorMessage: '未找到该菜单',
        success: false,
      });
      return;
    }
    Object.assign(
      editMenu,
      Object.entries(menuParams).reduce((result, [key, val]) => {
        if (!['id', 'pid'].includes(key)) {
          result[key] = val;
        }
        return result;
      }, {}),
    );
    if (!menuData.beUsedCode.includes(menuParams.menuCode)) {
      const oldMenuCodeIndex = menuData.beUsedCode.findIndex((item) => item === editMenu.menuCode);
      menuData.beUsedCode.splice(oldMenuCodeIndex, 1, menuParams.menuCode);
    }
    if (menuParams.pid === '0') {
      // 一级菜单，对新增菜单，已有菜单做排序
      menuData.menuTree.sort((pre, next) => pre.order - next.order);
    } else {
      // 非一级菜单，寻找添加菜单的上一级，对当前层级新增菜单，已有菜单做排序
      const currentMenu = findMenuById(menuData.menuTree, menuParams.pid);
      currentMenu?.children?.sort((pre, next) => pre.order - next.order);
    }
    fs.writeFileSync('./mock/database/menu.json', JSON.stringify(menuData));
    res.send({
      success: true,
      data: null,
    });
  },
  'DELETE /api/menu': async (req: Request, res: Response) => {
    const delParams = req.query as unknown as MENU.DeleteMenuParams;
    const validateFieldsArr = ['pid', 'id'];
    for (const key of validateFieldsArr) {
      if (!delParams[key] && menuErrMessageMap.hasOwnProperty(key)) {
        res.send({
          data: null,
          errorMessage: menuErrMessageMap[key],
          success: false,
        });
        return;
      }
    }
    const menuData = getMuneData();
    const delMenu = findMenuById(menuData.menuTree, delParams.id);
    if (!delMenu) {
      res.send({
        data: null,
        errorMessage: '未找到待删除菜单',
        success: false,
      });
      return;
    }

    if (delMenu.pid === '0') {
      const delIndex = menuData.menuTree.findIndex((item) => item.id === delParams.id);
      delIndex > -1 && menuData.menuTree.splice(delIndex, 1);
    } else {
      const delMenuParentMenu = findMenuById(menuData.menuTree, delParams.pid);
      const delChildMenuIndex = delMenuParentMenu?.children?.findIndex(
        (item) => item.id === delParams.id,
      );
      if (delChildMenuIndex !== undefined) {
        delChildMenuIndex > -1 && delMenuParentMenu?.children?.splice(delChildMenuIndex, 1);
      }
    }

    menuData.beUsedCode = menuData.beUsedCode.filter((code) => code !== delMenu.menuCode);
    menuData.beUsedId = menuData.beUsedId.filter((menuId) => menuId !== delMenu.id);
    fs.writeFileSync('./mock/database/menu.json', JSON.stringify(menuData));
    res.send({
      success: true,
      data: null,
    });
  },
};
